package com.wcq.studentbackend.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wcq.studentbackend.dto.GradeDTO;
import com.wcq.studentbackend.dto.GradeRequestDTO;
import com.wcq.studentbackend.dto.GradeStatsResponseDTO;
import com.wcq.studentbackend.entity.Exam;
import com.wcq.studentbackend.entity.Grade;
import com.wcq.studentbackend.entity.Student;
import com.wcq.studentbackend.mapper.GradeMapper;
import com.wcq.studentbackend.service.ExamService;
import com.wcq.studentbackend.service.GradeService;
import com.wcq.studentbackend.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class GradeServiceImpl extends ServiceImpl<GradeMapper, Grade> implements GradeService {

    private final StudentService studentService;
    private final ExamService examService;

    @Autowired
    public GradeServiceImpl(StudentService studentService, ExamService examService) {
        this.studentService = studentService;
        this.examService = examService;
    }

    // GradeMapper (this.baseMapper) 已被 ServiceImpl 注入

    @Override
    public List<GradeDTO> getAllGradesWithDetails() {
        // 使用 GradeMapper 中自定义的 findAllGradeDTOs 方法
        return baseMapper.findAllGradeDTOs();
    }

    @Override
    public GradeDTO getGradeWithDetailsById(Long id) {
        // 使用 GradeMapper 中自定义的 findGradeDTOById 方法
        return baseMapper.findGradeDTOById(id);
    }

    @Override
    @Transactional
    public GradeDTO createGrade(GradeRequestDTO gradeRequestDTO) {
        Student student = studentService.getById(gradeRequestDTO.getStudentId());
        if (student == null) {
            throw new IllegalArgumentException("学生ID " + gradeRequestDTO.getStudentId() + " 不存在。");
        }

        Exam exam = examService.getById(gradeRequestDTO.getExamId());
        if (exam == null) {
            throw new IllegalArgumentException("考试ID " + gradeRequestDTO.getExamId() + " 不存在。");
        }
        
        Grade gradeEntity = new Grade();
        BeanUtils.copyProperties(gradeRequestDTO, gradeEntity);
        LocalDateTime now = LocalDateTime.now();
        gradeEntity.setCreateTime(now);
        gradeEntity.setUpdateTime(now);
        
        save(gradeEntity); // 保存到数据库
        
        return baseMapper.findGradeDTOById(gradeEntity.getId());
    }

    @Override
    @Transactional
    public GradeDTO updateGrade(Long id, GradeRequestDTO gradeRequestDTO) {
        Grade gradeEntity = getById(id);
        if (gradeEntity == null) {
            return null;
        }
        if (gradeRequestDTO.getExamId() != null) {
            Exam exam = examService.getById(gradeRequestDTO.getExamId());
            if (exam == null) {
                throw new IllegalArgumentException("考试ID " + gradeRequestDTO.getExamId() + " 不存在。");
            }
            gradeEntity.setExamId(gradeRequestDTO.getExamId());
        }
        if (gradeRequestDTO.getScore() != null) {
            gradeEntity.setScore(gradeRequestDTO.getScore());
        }
        gradeEntity.setUpdateTime(LocalDateTime.now());
        updateById(gradeEntity);
        return baseMapper.findGradeDTOById(id);
    }

    @Override
    @Transactional
    public boolean deleteGrade(Long id) {
        return removeById(id);
    }

    @Override
    public List<GradeDTO> searchGrades(Long examId, Long classId, String studentName) {
        return baseMapper.searchGrades(examId, classId, studentName);
    }

    @Override
    public GradeStatsResponseDTO getStudentGradeStats(Long studentId) {
        List<GradeDTO> grades = baseMapper.findGradesByStudentId(studentId);
        GradeStatsResponseDTO statsDto = new GradeStatsResponseDTO();
        statsDto.setStudentId(studentId);

        Student studentForStats = studentService.getById(studentId);
        if (studentForStats != null) {
            statsDto.setStudentName(studentForStats.getName());
        } else {
            statsDto.setStudentName("N/A");
        }

        if (grades == null || grades.isEmpty()) {
            statsDto.setCount(0);
            statsDto.setAverage(0.0);
            statsDto.setMax(0);
            statsDto.setMin(0);
            statsDto.setSum(0);
            statsDto.setSubjectCount(new HashMap<>());
            return statsDto;
        }

        int count = grades.size();
        double avg = grades.stream().mapToInt(GradeDTO::getScore).average().orElse(0.0);
        int max = grades.stream().mapToInt(GradeDTO::getScore).max().orElse(0);
        int min = grades.stream().mapToInt(GradeDTO::getScore).min().orElse(0);
        int sum = grades.stream().mapToInt(GradeDTO::getScore).sum();

        Map<String, Long> subjectCountMap = new HashMap<>();
        grades.forEach(g -> {
            String subject = g.getExamSubject(); 
            if (subject != null) { 
                subjectCountMap.put(subject, subjectCountMap.getOrDefault(subject, 0L) + 1);
            }
        });

        statsDto.setCount(count);
        statsDto.setAverage(avg);
        statsDto.setMax(max);
        statsDto.setMin(min);
        statsDto.setSum(sum);
        statsDto.setSubjectCount(subjectCountMap);

        return statsDto;
    }

    @Override
    public List<GradeDTO> getGradesByStudentStuNo(String stuNo) {
        if (stuNo == null || stuNo.trim().isEmpty()) {
            log.warn("Attempted to get grades with null or empty stuNo.");
            return Collections.emptyList();
        }
        try {
            // 假设 GradeMapper 有一个方法可以直接查询并返回 GradeDTO 列表
            // 这个方法内部可能需要进行多表连接查询（例如，grades, exams, students 表）
            // 或者你可以先查询 Grade 实体，再转换为 GradeDTO
            List<GradeDTO> grades = baseMapper.selectGradeDTOsByStuNo(stuNo);
            log.info("Fetched {} grades for stuNo: {}", grades.size(), stuNo);
            return grades;
        } catch (Exception e) {
            log.error("Error fetching grades for stuNo: {}. Error: {}", stuNo, e.getMessage(), e);
            // 返回空列表而不是null，避免上游出现NullPointerException
            return Collections.emptyList();
        }
    }

} 